from typing import (
    Dict,
    Iterator,
)

from pydantic import __version__

if __version__.startswith("1"):  # Pydantic V1
    import pydantic.errors as pydantic_errors

else:
    import pydantic.v1.errors as pydantic_errors


class ErrorBase:
    """ 错误基类 """

    code: str
    """ 编号 """

    msg_template: str
    """ 错误消息模板 """

    msg_template_zh_cn: str
    """ 错误消息模板（中文） """


class PydanticTypeError:
    """ 类型错误 """

    code = "type_error"
    msg_template = "type is not valid"
    msg_template_zh_cn = "类型错误"

    class CallableError(ErrorBase):
        code = "callable"
        msg_template = pydantic_errors.CallableError.msg_template
        msg_template_zh_cn = "{value} 是不可调用的"

    class ClassError(ErrorBase):
        code = "class"
        msg_template = pydantic_errors.ClassError.msg_template
        msg_template_zh_cn = "应当是一个类"

    class DataclassTypeError(ErrorBase):
        code = "dataclass"
        msg_template = pydantic_errors.DataclassTypeError.msg_template
        msg_template_zh_cn = "应为 {class_name} 的实例、元组或字典"

    class DequeError(ErrorBase):
        code = "deque"
        msg_template = pydantic_errors.DequeError.msg_template
        msg_template_zh_cn = "数值不是有效的双向队列"

    class EnumError(ErrorBase):
        code = "enum_instance"
        msg_template = pydantic_errors.EnumError.msg_template
        msg_template_zh_cn = "{value} 不是一个有效的枚举实例"

    class FloatError(ErrorBase):
        code = "float"
        msg_template = pydantic_errors.FloatError.msg_template
        msg_template_zh_cn = "数值不是有效的小数"

    class FrozenSetError(ErrorBase):
        code = "frozenset"
        msg_template = pydantic_errors.FrozenSetError.msg_template
        msg_template_zh_cn = "数值不是有效的冻结集合"

    class FrozenSetMaxLengthError(ErrorBase):
        code = "frozenset.max_items"
        msg_template = pydantic_errors.FrozenSetMaxLengthError.msg_template
        msg_template_zh_cn = "请确保该冻结集合最多有 {limit_value} 个元素"

    class FrozenSetMinLengthError(ErrorBase):
        code = "frozenset.min_items"
        msg_template = pydantic_errors.FrozenSetMinLengthError.msg_template
        msg_template_zh_cn = "请确保该冻结集合至少有 {limit_value} 个元素"

    class HashableError(ErrorBase):
        code = "hashable"
        msg_template = pydantic_errors.HashableError.msg_template
        msg_template_zh_cn = "数值不是有效的可散列对象"

    class IntEnumError(ErrorBase):
        code = "int_enum_instance"
        msg_template = pydantic_errors.IntEnumError.msg_template
        msg_template_zh_cn = "{value} 不是一个有效的数字枚举实例"

    class IntegerError(ErrorBase):
        code = "integer"
        msg_template = pydantic_errors.IntegerError.msg_template
        msg_template_zh_cn = "数值不是有效的整数"

    class IterableError(ErrorBase):
        code = "iterable"
        msg_template = pydantic_errors.IterableError.msg_template
        msg_template_zh_cn = "数值不是有效的可迭代对象"

    class JsonTypeError(ErrorBase):
        code = "json"
        msg_template = pydantic_errors.JsonTypeError.msg_template
        msg_template_zh_cn = "JSON 对象必须是 str、bytes 或 bytearray 类型"

    class ListError(ErrorBase):
        code = "list"
        msg_template = pydantic_errors.ListError.msg_template
        msg_template_zh_cn = "数值不是有效的列表"

    class ListMaxLengthError(ErrorBase):
        code = "list.max_items"
        msg_template = pydantic_errors.ListMaxLengthError.msg_template
        msg_template_zh_cn = "请确保该列表最多有 {limit_value} 个元素"

    class ListMinLengthError(ErrorBase):
        code = "list.min_items"
        msg_template = pydantic_errors.ListMinLengthError.msg_template
        msg_template_zh_cn = "请确保该列表至少有 {limit_value} 个元素"

    class ListUniqueItemsError(ErrorBase):
        code = "list.unique_items"
        msg_template = pydantic_errors.ListUniqueItemsError.msg_template
        msg_template_zh_cn = "列表中有重复的元素"

    class MissingError(ErrorBase):
        code = "missing"
        msg_template = pydantic_errors.MissingError.msg_template
        msg_template_zh_cn = "字段是必填的"

    class NoneIsNotAllowedError(ErrorBase):
        code = "none.not_allowed"
        msg_template = pydantic_errors.NoneIsNotAllowedError.msg_template
        msg_template_zh_cn = "不允许为 None"

    class NoneIsAllowedError(ErrorBase):
        code = "none.allowed"
        msg_template = pydantic_errors.NoneIsAllowedError.msg_template
        msg_template_zh_cn = "值不是 None"

    class NotNoneError(ErrorBase):
        code = "not_none"
        msg_template = pydantic_errors.NotNoneError.msg_template
        msg_template_zh_cn = "值不是 None"

    class PathNotExistsError(ErrorBase):
        code = "path.not_exists"
        msg_template = pydantic_errors.PathNotExistsError.msg_template
        msg_template_zh_cn = "路径为 {path} 的文件或目录不存在"

    class PathNotAFileError(ErrorBase):
        code = "path.not_a_file"
        msg_template = pydantic_errors.PathNotAFileError.msg_template
        msg_template_zh_cn = "路径为 {path} 未指向文件"

    class PathNotADirectoryError(ErrorBase):
        code = "path.not_a_directory"
        msg_template = pydantic_errors.PathNotADirectoryError.msg_template
        msg_template_zh_cn = "路径为 {path} 未指向目录"

    class PathError(ErrorBase):
        code = "path"
        msg_template = pydantic_errors.PathError.msg_template
        msg_template_zh_cn = "数值不是有效的路径"

    class SequenceError(ErrorBase):
        code = "sequence"
        msg_template = pydantic_errors.SequenceError.msg_template
        msg_template_zh_cn = "数值不是有效的序列"

    class SetError(ErrorBase):
        code = "set"
        msg_template = pydantic_errors.SetError.msg_template
        msg_template_zh_cn = "数值不是有效的集合"

    class SetMaxLengthError(ErrorBase):
        code = "set.max_items"
        msg_template = pydantic_errors.SetMaxLengthError.msg_template
        msg_template_zh_cn = "请确保该集合最多有 {limit_value} 个元素"

    class SetMinLengthError(ErrorBase):
        code = "set.min_items"
        msg_template = pydantic_errors.SetMinLengthError.msg_template
        msg_template_zh_cn = "请确保该集合至少有 {limit_value} 个元素"

    class StrError(ErrorBase):
        code = "str"
        msg_template = pydantic_errors.StrError.msg_template
        msg_template_zh_cn = "数值不是有效的字符串"

    class StrRegexError(ErrorBase):
        code = "str.regex"
        msg_template = pydantic_errors.StrRegexError.msg_template
        msg_template_zh_cn = "数值不是有效的字符串"

    class SubclassError(ErrorBase):
        code = "subclass"
        msg_template = pydantic_errors.SubclassError.msg_template
        msg_template_zh_cn = "应当是 {expected_class} 的子类"

    class TupleError(ErrorBase):
        code = "tuple"
        msg_template = pydantic_errors.TupleError.msg_template
        msg_template_zh_cn = "字符串不符合正则表达式 {pattern}"

    class TupleLengthError(ErrorBase):
        code = "tuple.length"
        msg_template = pydantic_errors.TupleLengthError.msg_template
        msg_template_zh_cn = "元组长度错误，实际长度为 {actual_length}，期望长度为 {expected_length}"

    class UUIDError(ErrorBase):
        code = "uuid"
        msg_template = pydantic_errors.UUIDError.msg_template
        msg_template_zh_cn = "数值不是有效的 UUID"

    class UUIDVersionError(ErrorBase):
        code = "uuid.version"
        msg_template = pydantic_errors.UUIDVersionError.msg_template
        msg_template_zh_cn = "UUID 版本 {required_version} 未符合预期"


class PydanticValueError:
    """ 值错误 """

    code = "value_error"
    msg_template = "value is not valid"
    msg_template_zh_cn = "值错误"

    class AnyStrMaxLengthError(ErrorBase):
        code = "any_str.max_length"
        msg_template = pydantic_errors.AnyStrMaxLengthError.msg_template
        msg_template_zh_cn = "请确保这个值最多有 {limit_value} 个字符"

    class AnyStrMinLengthError(ErrorBase):
        code = "any_str.min_length"
        msg_template = pydantic_errors.AnyStrMinLengthError.msg_template
        msg_template_zh_cn = "请确保这个值至少有 {limit_value} 个字符"

    class BoolError(ErrorBase):
        code = "bool"
        msg_template = pydantic_errors.BoolError.msg_template
        msg_template_zh_cn = "值无法解析为布尔值"

    class BytesError(ErrorBase):
        code = "bool"
        msg_template = pydantic_errors.BytesError.msg_template
        msg_template_zh_cn = "预期为 byte 类型"

    class ColorError(ErrorBase):
        code = "color"
        msg_template = pydantic_errors.ColorError.msg_template
        msg_template_zh_cn = "该值不是一个有效的颜色: {reason}"

    class DateError(ErrorBase):
        code = "date"
        msg_template = pydantic_errors.DateError.msg_template
        msg_template_zh_cn = "无效的日期格式"

    class DateNotInTheFutureError(ErrorBase):
        code = "date.not_in_the_future"
        msg_template = pydantic_errors.DateNotInTheFutureError.msg_template
        msg_template_zh_cn = "日期不是未来的日期"

    class DateNotInThePastError(ErrorBase):
        code = "date.not_in_the_past"
        msg_template = pydantic_errors.DateNotInThePastError.msg_template
        msg_template_zh_cn = "日期不是过去的日期"

    class DateTimeError(ErrorBase):
        code = "datetime"
        msg_template = pydantic_errors.DateTimeError.msg_template
        msg_template_zh_cn = "无效的日期时间格式"

    class DictError(ErrorBase):
        code = "dict"
        msg_template = pydantic_errors.DictError.msg_template
        msg_template_zh_cn = "数值不是有效的字典"

    class DecimalError(ErrorBase):
        code = "decimal"
        msg_template = pydantic_errors.DecimalError.msg_template
        msg_template_zh_cn = "数值不是有效的十进制数"

    class DecimalIsNotFiniteError(ErrorBase):
        code = "decimal.not_finite"
        msg_template = pydantic_errors.DecimalIsNotFiniteError.msg_template
        msg_template_zh_cn = "数值不是有效的十进制数"

    class DecimalMaxDigitsError(ErrorBase):
        code = "decimal.max_digits"
        msg_template = pydantic_errors.DecimalMaxDigitsError.msg_template
        msg_template_zh_cn = "请确保总共不超过 {max_digits} 位数字"

    class DecimalMaxPlacesError(ErrorBase):
        code = "decimal.max_places"
        msg_template = pydantic_errors.DecimalMaxPlacesError.msg_template
        msg_template_zh_cn = "请确保小数部分不超过 {decimal_places} 位"

    class DecimalWholeDigitsError(ErrorBase):
        code = "decimal.whole_digits"
        msg_template = pydantic_errors.DecimalWholeDigitsError.msg_template
        msg_template_zh_cn = "请确保小数点前不超过 {whole_digits} 位数字"

    class DurationError(ErrorBase):
        code = "duration"
        msg_template = pydantic_errors.DurationError.msg_template
        msg_template_zh_cn = "无效的持续时间格式"

    class EmailError(ErrorBase):
        code = "email"
        msg_template = pydantic_errors.EmailError.msg_template
        msg_template_zh_cn = "数值不是有效的邮箱地址"

    class EnumMemberError(ErrorBase):
        code = "enum"
        msg_template = "value is not a valid enumeration member; permitted: {enum_values}:"  # EnumMemberError.__str__
        msg_template_zh_cn = "该数值不是有效的枚举成员；允许的值包括 {enum_values}"

    class ExtraError(ErrorBase):
        code = "extra"
        msg_template = pydantic_errors.ExtraError.msg_template
        msg_template_zh_cn = "不允许额外字段"

    class JsonError(ErrorBase):
        code = "json"
        msg_template = pydantic_errors.JsonError.msg_template
        msg_template_zh_cn = "无效的 JSON"

    class NumberNotFiniteError(ErrorBase):
        code = "number.not_finite_number"
        msg_template = pydantic_errors.NumberNotFiniteError.msg_template
        msg_template_zh_cn = "请确保该值是一个有限数"

    class NumberNotMultipleError(ErrorBase):
        code = "number.not_multiple"
        msg_template = pydantic_errors.NumberNotMultipleError.msg_template
        msg_template_zh_cn = "请确保该值是 {multiple_of} 的倍数"

    class NumberNotGeError(ErrorBase):
        code = "number.not_ge"
        msg_template = pydantic_errors.NumberNotGeError.msg_template
        msg_template_zh_cn = "请确保该值大于等于 {limit_value}"

    class NumberNotGtError(ErrorBase):
        code = "number.not_gt"
        msg_template = pydantic_errors.NumberNotGtError.msg_template
        msg_template_zh_cn = "请确保该值大于 {limit_value}"

    class NumberNotLeError(ErrorBase):
        code = "number.not_le"
        msg_template = pydantic_errors.NumberNotLeError.msg_template
        msg_template_zh_cn = "请确保该值小于等于 {limit_value}"

    class NumberNotLtError(ErrorBase):
        code = "number.not_lt"
        msg_template = pydantic_errors.NumberNotLtError.msg_template
        msg_template_zh_cn = "请确保该值小于 {limit_value}"

    class PatternError(ErrorBase):
        code = "regex_pattern"
        msg_template = pydantic_errors.PatternError.msg_template
        msg_template_zh_cn = "无效的正则表达式"

    class StrictBoolError(ErrorBase):
        code = "strictbool"  # noqa: ignore spell
        msg_template = pydantic_errors.StrictBoolError.msg_template
        msg_template_zh_cn = "值不是有效的布尔值"

    class TimeError(ErrorBase):
        code = "time"
        msg_template = pydantic_errors.TimeError.msg_template
        msg_template_zh_cn = "无效的时间格式"

    class UrlSchemeError(ErrorBase):
        code = "url.scheme"
        msg_template = pydantic_errors.UrlSchemeError.msg_template
        msg_template_zh_cn = "无效或缺失的 URL"

    class WrongConstantError(ErrorBase):
        code = "const"
        msg_template = "unexpected value; permitted: {permitted}"  # WrongConstantError.__str__
        msg_template_zh_cn = "不符合预期的值，允许的值 {permitted}"


error_msg_templates: Dict[str, str] = {}
""" 错误消息模板 """

error_msg_templates_zh_cn: Dict[str, str] = {}
""" 错误消息模板（中文） """

for error in (PydanticTypeError, PydanticValueError):
    code: str = error.code
    sub_error_list: Iterator[type[ErrorBase]] = (
        cls
        for cls in error.__dict__.values()
        if (
            isinstance(cls, type)
            and issubclass(cls, ErrorBase)
        )
    )

    for sub_error in sub_error_list:
        error_code: str = f"{code}.{sub_error.code}"
        error_msg_templates[error_code] = sub_error.msg_template
        error_msg_templates_zh_cn[error_code] = sub_error.msg_template_zh_cn
